#include "Client.h"

#include <sstream>
#include <sys/time.h>

#include <Utils.h>
#include <Constantes.h>
#include <ConfigurationFile.h>
#include <Serializable.h>

Client::Client()
: m_ReceptorFifoAbierto(false)
{
	m_Log = Logger::getInstance();
}

Client::~Client()
{
	
}

void Client::joinChiefClientQueue()
{
	// Intento unirme al fifo del jefe para registrarme
	std::string senderFifoPathName = ConfigurationFile::getProperty(Properties::COLA_CLIENTE);
	bool protectAccess = true;
	m_ReceptorJefe.crear(senderFifoPathName, CreationMode::DEBE_EXISTIR, protectAccess);
	m_ReceptorJefe.abrir();
}

void Client::createInstructionReceptor()
{
	// Creo un fifo de recepcion donde me notificaran instrucciones
	std::string strPID = Utils::convertIntToStr(getpid());
	m_ReceptorFifoPathName = "/tmp/cliente_" + strPID;
	
	m_Log->debug("CLIENTE >> Creando receptor "+m_ReceptorFifoPathName);
	bool protectAccess = false;
	m_ReceptorFifo.crear(m_ReceptorFifoPathName,CreationMode::NO_DEBE_EXISTIR, protectAccess);
}

void Client::checkInAttQueue()
{
	try
	{
		// Agrego el nombre de mi receptor al fifo del jefe
		m_MessageTxRx.enviarAtributoAReceptor(m_ReceptorJefe,MessageKey::PATH_FIFO,m_ReceptorFifoPathName);
	}
	catch (const BaseException& e)
	{
		std::stringstream eMsg;
		eMsg << "No se pudo registrar en cola de atencion a clientes del jefe.";
		eMsg << e.what() << ". Cliente se retira";
		throw BaseException(eMsg.str(), Client::RETREATE_EXIT);
	}
}

std::string Client::retrieveInstructions()
{
	this->abrirReceptorFifo();
	return m_MessageTxRx.obtenerAtributoDeReceptor(m_ReceptorFifo, MessageKey::INSTRUCCION);
}

bool Client::shouldLeave(const std::string& instruction) const
{
	return (instruction.compare(InstructionValue::FINALIZAR) == 0);
}

bool Client::hasBeenAssisted(const std::string& instruction) const
{
	return (instruction.compare(InstructionValue::DAME_MONTO) == 0);
}

void Client::askForGas(int amount)
{
	std::string amountStr = Utils::convertIntToStr(amount);
	
	// Obtengo datos del empleado que me atendio
	std::string employeeFifoPath = m_MessageTxRx.obtenerAtributoDeReceptor(m_ReceptorFifo, MessageKey::PATH_FIFO);
	
	// Envio el monto requerido al fifo del playero
	bool protectAccess = true;
	FifoEscritura receptorPlayero(employeeFifoPath, CreationMode::DEBE_EXISTIR, protectAccess);
	receptorPlayero.abrir();
	m_MessageTxRx.enviarAtributoAReceptor(receptorPlayero, MessageKey::TOMA_MONTO, amountStr);
	receptorPlayero.cerrar();
}

void Client::abrirReceptorFifo()
{
	if(!m_ReceptorFifoAbierto)
	{
		m_Log->debug("CLIENTE >> Abriendo FIFO receptor de instrucciones");
		m_ReceptorFifo.abrir();
		m_ReceptorFifoAbierto = true;
	}
}
